/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ui;

import control.MStockMidlet;
import font.MyFont;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Graphics;
import listener.Command;
import listener.ICompleteListener;
import util.SoftKey;

/**
 *
 * @author tho.hoang
 */
public class DateFieldEditor extends Canvas {

    private int valueIndex = 0, preValueIndex = -1, numIndex = 0;
    char[] numChars = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
    boolean motorola = false, isSignedChar = false;
    final int KEY_SOFT_LEFT = -6, KEY_SOFT_RIGHT = -7, KEY_UP = -1, KEY_LEFT = -3, KEY_DOWN = -2, KEY_RIGHT = -4, KEY_FIRE = -5;
    private boolean sameField = false;
    private char curChar;
    private Style headerStyle, footerStyle, textBoxStyle;
    private Display display;
    private ICompleteListener listener;
    private Command selectCommand, cancelCommand;
    private MyFont font;
    private int textHeight;
    private String label, error = "Ngày không đúng", id;
    private int[] value = new int[3], valueX = new int[3], valueWitdh = new int[3], maxValue = {31, 12, 9999};// day, month, year;
    private Date date;
    private int dateWidth;
    private int vx;

    public DateFieldEditor(Display display, MStockMidlet control, String id, String label, Date date) {
        setFullScreenMode(true);
        this.display = display;
        this.font = control.getFont();
        this.footerStyle = control.getStyle().getFooterStyle();
        this.headerStyle = control.getStyle().getHeaderStyle();
        this.textBoxStyle = control.getStyle().getTextBoxStyle();
        this.cancelCommand = new Command("Trở về", Command.BACK);
        this.selectCommand = new Command("Đồng ý", Command.OK);
        this.textHeight = font.getFontNormal().getHeight();
        this.dateWidth = font.getFontNormal().stringWidth("00/00/0000");
        this.vx = (getWidth() - dateWidth) / 2;
        this.valueX[0] = vx;
        this.valueX[1] = vx + font.getFontNormal().stringWidth("00/");
        this.valueX[2] = vx + font.getFontNormal().stringWidth("00/00/");
        this.valueWitdh[0] = this.valueWitdh[1] = font.getFontNormal().stringWidth("00");
        this.valueWitdh[2] = font.getFontNormal().stringWidth("0000");
        this.id = id;
        this.label = label;
        if (date != null) {
            this.date = date;
        }
        setValue();
    }

    public void show() {
        this.display.setCurrent(this);
    }

    public void setListener(ICompleteListener listener) {
        this.listener = listener;
    }

    public Date getDate() {
        Calendar ca = Calendar.getInstance();
        TimeZone tz = TimeZone.getTimeZone("GMT+07:00");
        ca.setTimeZone(tz);
        ca.set(Calendar.DAY_OF_MONTH, value[0]);
        ca.set(Calendar.MONTH, value[1] - 1);
        ca.set(Calendar.YEAR, value[2]);
        date = ca.getTime();
        return date;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setDate(Date date) {
        if (date != null) {
            this.date = date;
            setValue();
        }
    }

    protected void keyRepeated(int keyCode) {
        keyCode = changeKeyCode(keyCode);
        processKeyRepeated(keyCode);
    }

    protected void keyPressed(int keyCode) {
        keyCode = changeKeyCode(keyCode);
        if (keyCode == KEY_SOFT_LEFT) {
            // validate date
            if (validateDate(value[0], value[1], value[2])) {
                if (listener != null) {
                    listener.completedAction(this, getDate());
                }
            }
        } else if (keyCode == KEY_SOFT_RIGHT) {
            if (listener != null) {
                listener.completedAction(this, null);
            }
        } else {
            processKeyPress(keyCode);
            repaint();
        }

    }

    protected void paint(Graphics g) {
        setFullScreenMode(true);
        initGui();
        int height = headerStyle.getHeight() + textBoxStyle.getHeight() + footerStyle.getHeight();
        int x = 0, y = getHeight() - height, headerH = 0;

        // bg header
        g.setColor(headerStyle.getBgColor());
        g.fillRect(x, y, getWidth(), headerStyle.getHeight());
        // label
        if (validateDate(value[0], value[1], value[2])) {
            font.getFontBold().drawString(g, label, getWidth() / 2, y + headerStyle.getPadding().getTop(), Graphics.TOP | Graphics.HCENTER);

        } else {
            font.getFontBold().drawString(g, error, getWidth() / 2, y + headerStyle.getPadding().getTop(), Graphics.TOP | Graphics.HCENTER);
        }

        y += headerStyle.getHeight();
        // bg text box
        g.setColor(textBoxStyle.getSelectedBgColor());
        g.fillRect(x, y, getWidth(), textBoxStyle.getHeight());
        // box
        g.setColor(textBoxStyle.getSelectedBorderColor());
        g.drawRect(x, y, getWidth() - 1, textBoxStyle.getHeight() - 1);

        /* draw background */
        g.setColor(textBoxStyle.getSelectedBorderColor());
        g.fillRect(valueX[valueIndex], y + textBoxStyle.getPadding().getTop(), valueWitdh[valueIndex], textHeight);
        // text
        String text = formatNumber(this.value[0], 2) + "/" + formatNumber(this.value[1], 2) + "/" + formatNumber(this.value[2], 4);
        font.getFontNormal().drawString(g, text, vx, y + textBoxStyle.getPadding().getTop(), Graphics.TOP | Graphics.LEFT);

        y += textBoxStyle.getHeight();
        // bg footer
        g.setColor(footerStyle.getBgColor());
        g.fillRect(x, y, getWidth(), footerStyle.getHeight());
        // left command
        if (selectCommand != null) {
            font.getFontBold().drawString(g, selectCommand.getText(), x + footerStyle.getPadding().getLeft(), y + footerStyle.getPadding().getTop(), Graphics.TOP | Graphics.LEFT);
        }
        // right command
        if (cancelCommand != null) {
            font.getFontBold().drawString(g, cancelCommand.getText(), getWidth() - footerStyle.getPadding().getRight(), y + footerStyle.getPadding().getTop(), Graphics.TOP | Graphics.LEFT);
        }

        System.gc();
    }

    private void initGui() {
        // init header
        int headerH = 0;
        if (label != null && label.length() > 0) {
            headerH = font.getFontBold().getHeight();
        }
        headerStyle.setHeight(headerH + headerStyle.getPadding().getTopAndBottom());

        // init Text Box
        textBoxStyle.setHeight(font.getFontNormal().getHeight() + textBoxStyle.getPadding().getTopAndBottom() + 2);

        // init footer
        if (selectCommand != null || cancelCommand != null) {
            footerStyle.setHeight(font.getFontBold().getHeight() + footerStyle.getPadding().getTopAndBottom());
        } else {
            footerStyle.setHeight(0);
        }
    }

    private String formatNumber(int num, int degit) {
        String re = num + "";
        while (re.length() < degit) {
            re = "0" + re;
        }
        return re;
    }

    private void deleteChar() {
        value[valueIndex] = 0;
    }

    private void processKeyPress(int keyCode) {
        preValueIndex = valueIndex;

        int action = getGameAction(keyCode);
        /* check if pressing from number 1 to 9 */
        if (keyCode >= KEY_NUM0 && keyCode <= KEY_NUM9) {
            numIndex = keyCode - KEY_NUM0;
            insertChar();
        } else if (keyCode == KEY_STAR) {
        } else if (action == UP) {
        } else if (action == DOWN) {
        } else if (action == LEFT) {
            valueIndex = (valueIndex + 2) % 3;
            sameField = false;
            repaint();
        } else if (action == RIGHT) {
            valueIndex = (valueIndex + 1) % 3;
            sameField = false;
            repaint();
        }
    }

    private int changeKeyCode(int keyCode) {
        int key = keyCode;
        if (keyCode == SoftKey.getLeftSoftkeyCode(this)) {
            key = KEY_SOFT_LEFT;

        } else if (keyCode == SoftKey.getRightSoftkeyCode(this)) {
            key = KEY_SOFT_RIGHT;

        } else {
            switch (keyCode) {
                case KEY_NUM0:
                case KEY_NUM1:
                case KEY_NUM2:
                case KEY_NUM3:
                case KEY_NUM4:
                case KEY_NUM5:
                case KEY_NUM6:
                case KEY_NUM7:
                case KEY_NUM8:
                case KEY_NUM9:
                case KEY_STAR:
                case KEY_POUND:
                case FIRE:
                    key = keyCode;
                    break;
                default:
                    int gameAction = getGameAction(keyCode);
                    switch (gameAction) {
                        case UP:
                            key = KEY_UP;
                            break;
                        case DOWN:
                            key = KEY_DOWN;
                            break;
                        case LEFT:
                            key = KEY_LEFT;
                            break;
                        case RIGHT:
                            key = KEY_RIGHT;
                            break;
                    }
                    break;
            }
        }
        return key;
    }

    private void insertChar() {
        /* check if edit same field */
        if (valueIndex != preValueIndex && !sameField) {
            deleteChar();
        }
        char ch = getInsertedChar();
        int num = Integer.parseInt(ch + "");
        int[] tem = value;
        int newNum = value[valueIndex] * 10 + num;
        if (newNum <= maxValue[valueIndex]) {
            tem[valueIndex] = newNum;
            if (validateDate(tem[0], tem[1], tem[2])) {
                value[valueIndex] = newNum;
            }
        } else {
            tem[valueIndex] = num;
            if (validateDate(tem[0], tem[1], tem[2])) {
                value[valueIndex] = num;
            }
        }
        sameField = true;
    }

    private char getInsertedChar() {
        /** get current char */
        curChar = numChars[numIndex];
        return curChar;
    }

    private void processKeyRepeated(int keyCode) {
        processKeyPress(keyCode);
    }

    private void setValue() {
        Calendar ca = Calendar.getInstance();
        if (this.date != null) {
            ca.setTime(date);
        }
        this.value[0] = ca.get(Calendar.DAY_OF_MONTH);
        this.value[1] = ca.get(Calendar.MONTH) + 1;
        this.value[2] = ca.get(Calendar.YEAR);
    }

    private boolean validateDate(int day, int month, int year) {
        int[] days = new int[]{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if (isLeapYear(year)) {
            days[2] = 29;
        }
        if (month == 0 || month > days.length) {
            return false;
        }
        if (day == 0 || day > days[month]) {
            return false;
        }
        return true;
    }

    private boolean isLeapYear(int year) {
        if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
            return true;
        }
        return false;
    }
}
